/*
 * @Author: hc
 * @Date: 2024-03-05 10:34:26
 * @LastEditTime: 2024-03-05 21:19:11
 * @LastEditors: hc
 * @Description:
 */
import { useHistoryTravel, useMemoizedFn } from 'ahooks';
import { Input } from 'antd';
import { forwardRef, useImperativeHandle, useRef } from 'react';
import { flushSync } from 'react-dom';
import { insertContent, TextareaEditorAPI } from './types';
import { getCursorPosition, setCursorPosition } from './utils';

const TextareaEditor = forwardRef<unknown & TextareaEditorAPI>((_, ref) => {
  const { value, setValue, back, forward, reset } = useHistoryTravel<string>('');

  const textAreaRef = useRef<any>();

  const cursorRef = useRef({
    start: 0,
    end: 0
  });

  /**
   * 记录光标位置
   */
  const handleRecordCursorPosition = () => {
    const position = getCursorPosition(textAreaRef.current);
    cursorRef.current = position;
  };

  /**
   * 值变动
   */
  const handleOnChange = (e) => {
    setValue(e.target.value);
    handleRecordCursorPosition();
  };

  /**
   * 文本插入
   */
  const insertEdit = useMemoizedFn(({ text, type }: insertContent) => {
    let newText = '';
    const insertStart = cursorRef.current.start;
    const insertEnd = cursorRef.current.end + text.length + 1;
    if (type === 'field') {
      newText = `${value?.slice(0, insertStart) ?? ''}${text} ${value?.slice(insertStart) ?? ''}`;
    } else {
      newText = `${value?.slice(0, insertStart) ?? ''}${text}()${value?.slice(insertStart) ?? ''}`;
    }
    setValue(newText);
    setTimeout(() => flushSync(() => setCursorPosition(textAreaRef.current, insertEnd, insertEnd)), 50);
  });

  /**
   * 获取已输入文本
   */
  const getHtmlValue = () => {
    return value ?? '';
  };

  /**
   * 设置输入文本
   */
  const setDefaultHtml = (str: string) => {
    setValue(str ?? '');
  };

  useImperativeHandle(ref, () => ({
    insertEdit,
    getHtmlValue,
    setDefaultHtml,
    back,
    forward,
    reset
  }));

  return (
    <Input.TextArea
      style={{ height: '100%' }}
      ref={textAreaRef}
      placeholder="请输入文本/插入函数或变量..."
      value={value}
      onChange={handleOnChange}
      onBlur={handleRecordCursorPosition}
    />
  );
});

export default TextareaEditor;
